using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using IQIGame.Onigao.GamePlay;
using System.Collections.Generic;

namespace IQIGame.Onigao.Logic
{
    /// <summary>
    /// 怪物巡逻组件
    /// </summary>
    public class LgEntityPatrolComponent : LogicBaseEntityComponent
    {
        public override uint MaxStore => 50;

        private LevelEntity _entity;
        private EntityParamPatrolPath _patrolParam;
        private int _curPatrolIndex = -1;
        /// <summary>
        /// 等待进入下一次寻路（巡逻点上发呆的时长）持续的帧数
        /// -1（无效状态），0（开始计时）
        /// </summary>
        private int _waitForNextPathFrame = -1;
        /// <summary>
        /// 当前节点需要等待的时间
        /// </summary>
        private int _waitTotalFrame = 0;
        private bool _isActive;
        private IReadOnlyList<Vector3Int> _patrolPath;
        private IReadOnlyList<int> _patrolWaitTime;

        public override void Awake(BaseEntity entity)
        {
            _entity = entity as LevelEntity;
            if (_entity.entityConfig.paramMap.TryGetValue(EntityDynamicParamType.PatrolPath, out var dynParam))
            {
                _patrolParam = dynParam as EntityParamPatrolPath;
            }
            ConfirmPatrolPath();
            //找到离当前位置最近的巡逻点索引(适应正常巡逻和返回追击开始点两种情况)
            _curPatrolIndex = -1;
            if (_patrolParam != null && _patrolPath != null && _patrolPath.Count > 1)
            {
                float minDistance = int.MaxValue;
                for (int i = 0; i < _patrolPath.Count; i++)
                {
                    Vector3Logic pos = _patrolPath[i];
                    float sqrDis = (pos - _entity.position).sqrMagnitude;
                    if (sqrDis > LgLevelConst.SamePositionSqrtRange && sqrDis < minDistance)
                    {
                        minDistance = sqrDis;
                        _curPatrolIndex = i;
                    }
                }
            }
            else
            {
                LogicLog.LogError("开启了巡逻但却没有配置巡逻路径");
            }
        }

        /// <summary>
        /// 确定巡逻路径
        /// </summary>
        private void ConfirmPatrolPath()
        {
            if (_patrolParam == null || _patrolParam.patrolPath.Count <= 1)
            {
                return;
            }
            if (!_patrolParam.randomPatrol || _patrolParam.patrolPath.Count <= 2)
            {
                _patrolPath = _patrolParam.patrolPath;
                _patrolWaitTime = _patrolParam.patrolWaitTime ?? new List<int>();
            }
            else
            {
                _patrolPath ??= new List<Vector3Int>();
                _patrolWaitTime ??= new List<int>();
                var randomPath = _patrolPath as List<Vector3Int>;
                var randomWaitTime = _patrolWaitTime as List<int>;
                randomPath.Clear();
                randomWaitTime.Clear();

                var random = _entity.region.level.random;
                //计算随机开始点，-1是要留至少一个给结束点，使开始点和结束点不是同一个，才能巡逻
                int startIndex = random.randomInt(_patrolParam.patrolPath.Count - 1);
                //计算结束点，先排除开始点之前所有点，再加上开始点之前所有点的数量
                int endIndex = random.randomInt(_patrolParam.patrolPath.Count - (startIndex + 1)) + (startIndex + 1);
                //填充数据
                for (int i = startIndex; i <= endIndex; i++)
                {
                    randomPath.Add(_patrolParam.patrolPath[i]);
                    randomWaitTime.Add(_patrolParam.patrolWaitTime[i]);
                }
            }
        }

        /// <summary>
        /// 开始巡逻
        /// </summary>
        public void StartPatrol()
        {
            _isActive = true;
            if (_curPatrolIndex != -1)
            {
                HeadToPatrolPoint();
            }
        }

        private void HeadToPatrolPoint()
        {
            _entity.StartNavigation(_patrolPath[_curPatrolIndex]);
        }

        public override void LogicOnUpdate()
        {
            if (!_isActive)
            {
                return;
            }
            //刷新巡逻时走到路径点时的暂停和切换巡逻点
            //如果该怪物没有巡逻点则不处理该逻辑
            //只有当怪物没有巡逻点时，在初始化时_curPatrolIndex才会==-1
            if (_curPatrolIndex != -1)
            {
                if (!_entity.navigator.isNavigating && _waitForNextPathFrame == -1) //停止寻路（到达路径点）且未开始等待
                {
                    //切换巡逻路径点，开始等待
                    _curPatrolIndex++;
                    if (_curPatrolIndex >= _patrolPath.Count)
                    {
                        _curPatrolIndex = 0;
                        ConfirmPatrolPath();
                    }
                    int configWaitMilliSec = _curPatrolIndex < _patrolWaitTime.Count ? _patrolWaitTime[_curPatrolIndex] : 0;
                    if (configWaitMilliSec == -1)
                    {
                        configWaitMilliSec = _entity.region.level.random.randomInt(LgLevelConst.PatrolRandomWaitMaxMilliSec);
                    }
                    _waitTotalFrame = (int)((float)configWaitMilliSec / 1000 * LgLevelConst.FrameRate);
                    _waitForNextPathFrame = 0;
                }
                else if (_waitForNextPathFrame != -1) //如果开始等待，则在巡逻路径点上停留一段时间后再继续下一段巡逻
                {
                    _waitForNextPathFrame++;
                    if (_waitForNextPathFrame >= _waitTotalFrame)
                    {
                        _waitForNextPathFrame = -1;
                        HeadToPatrolPoint();
                    }
                }
                //注意如果是寻路暂停状态（navigator.isActive == false）,isNavigating仍然是true，此时也认为怪物正在寻路，上面的逻辑都不会运行
            }
        }

        public void SetActive(bool value)
        {
            _isActive = value;
            _entity?.navigator.SetActive(value);
        }

        public override void OnRelease()
        {
            if (_entity.navigator.isNavigating)
            {
                _entity.StopNavigation();
            }
            _entity = null;
            _patrolParam = null;
            _curPatrolIndex = -1;
            _waitForNextPathFrame = -1;
            _waitTotalFrame = 0;
            _isActive = false;
            _patrolPath = null;
            _patrolWaitTime = null;
        }
    }
}
